/*
 * MainFrame.java
 *
 * Created on 12/12/2011, 20:16:11
 */

package br.mg.bhe.ftpobre.gui;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JEditorPane;
import javax.swing.JTable;
import javax.swing.table.TableColumnModel;

import br.mg.bhe.ftpobre.ConnectionData;
import br.mg.bhe.ftpobre.Main;
import br.mg.bhe.ftpobre.command.CommandFactory;
import br.mg.bhe.ftpobre.command.DeleteLocalFileCommand;
import br.mg.bhe.ftpobre.command.DeleteRemoteFileCommand;
import br.mg.bhe.ftpobre.command.DisconnectionCommand;
import br.mg.bhe.ftpobre.command.ICommand;
import br.mg.bhe.ftpobre.command.RefreshLocalFilesViewCommand;
import br.mg.bhe.ftpobre.command.RefreshRemoteFilesViewCommand;
import br.mg.bhe.ftpobre.command.facade.DeleteFileFacade;
import br.mg.bhe.ftpobre.command.facade.FileFacade;
import br.mg.bhe.ftpobre.command.facade.ServerFacade;
import br.mg.bhe.ftpobre.fs.FileNameGenerator;
import br.mg.bhe.ftpobre.fs.LocalFile;
import br.mg.bhe.ftpobre.fs.RemoteFile;
import br.mg.bhe.ftpobre.fs.data.xml.XmlFacade;
import br.mg.bhe.ftpobre.gui.connection.ConnectionFrame;
import br.mg.bhe.ftpobre.gui.fs.FileTableModelBuilder;
import br.mg.bhe.ftpobre.gui.help.AboutFrame;
import br.mg.bhe.ftpobre.gui.popup.LocalFilePopup;
import br.mg.bhe.ftpobre.gui.popup.LocalFolderPopup;
import br.mg.bhe.ftpobre.gui.popup.RemoteFilePopup;
import br.mg.bhe.ftpobre.gui.popup.RemoteFolderPopup;
import br.mg.bhe.ftpobre.log.FtpLogView;
import br.mg.bhe.ftpobre.util.LocalFileUtil;
import br.mg.bhe.ftpobre.util.LogUtil;
import br.mg.bhe.ftpobre.util.MensagensUtil;
import br.mg.bhe.ftpobre.util.RemoteFileUtil;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyListener;
import javax.swing.ButtonGroup;

/**
 *
 * @author Aureliano
 */
public class MainFrame extends javax.swing.JFrame {

	private static final Logger logger = LogUtil.getLogger(MainFrame.class);
	
    private static MainFrame mainFrame;
    private static String OS = System.getProperty("os.name").toLowerCase();

    public static MainFrame getInstance() {
        if (mainFrame == null) {
            mainFrame = new MainFrame();
        }

        return mainFrame;
    }
    
    public JEditorPane getEditorPaneLog() {
    	return this.editorPaneLog;
    }
    
    public JTable getTableLocalFiles() {
    	return this.tableLocalFiles;
    }
    
    public JTable getTableRemoteFiles() {
    	return this.tableRemoteFiles;
    }
    
    public Stack<String> getLocalFilePath() {
    	return this.localFilePath;
    }
    
    public Stack<String> getRemoteFilePath() {
    	return this.remoteFilePath;
    }

    /** Creates new form MainFrame */
    private MainFrame() {
    	this.localFilePath = new Stack<String>();
    	this.remoteFilePath = new Stack<String>();
        initComponents();
        this.addEventsComponents();
        this.createOperationModeButtonGroup();
    }
    
    private void addEventsComponents() {
        super.addWindowListener(new WindowAction());
        this.tableLocalFiles.addMouseListener(new TableLocalFileOpenPathAction());
        this.tableLocalFiles.addMouseListener(new TableLocalFilePopup());
        this.tableLocalFiles.addKeyListener(new TableLocalFileOpenPathAction());
        this.tableRemoteFiles.addMouseListener(new TableRemoteFileOpenPathAction());
        this.tableRemoteFiles.addMouseListener(new TableRemoteFilePopup());
        this.tableRemoteFiles.addKeyListener(new TableRemoteFileOpenPathAction());
    }
    
    private void createOperationModeButtonGroup() {
        ButtonGroup group = new ButtonGroup();
        group.add(this.radioButtonMenuItemOnline);
        group.add(this.radioButtonMenuItemOffline);
    }
    
    public String getAbsolutePathFromLocalFilePath() {
    	StringBuilder sb = new StringBuilder();
    	if (!OS.startsWith("windows")) {
    		sb.append("/");
    	}
    	
    	for (String token : this.localFilePath) {
    		sb.append(token).append(File.separator);
    	}
    	
    	return sb.substring(0, sb.length() - 1);
    }
    
    public String getAbsolutePathFromRemoteFilePath() {
    	StringBuilder sb = new StringBuilder();
    	
    	for (String token : this.remoteFilePath) {
    		sb.append(token).append("/");
    	}
    	
    	String path = sb.toString();
    	return ((path.length() > 1) && (path.charAt(path.length() - 1) == '/')) ? path.substring(0, sb.length() - 1) : path;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panelToolBox = new javax.swing.JPanel();
        toolBarFastAccess = new javax.swing.JToolBar();
        buttonConnect = new javax.swing.JButton();
        buttonDisconnect = new javax.swing.JButton();
        separatorFastAccess = new javax.swing.JToolBar.Separator();
        labelOperationMode = new javax.swing.JLabel();
        splitPaneContainer = new javax.swing.JSplitPane();
        splitPaneFileManager = new javax.swing.JSplitPane();
        panelLocalFiles = new javax.swing.JPanel();
        toolBarLocalFiles = new javax.swing.JToolBar();
        buttonEnviar = new javax.swing.JButton();
        buttonNewFolderLocal = new javax.swing.JButton();
        buttonRefreshLocal = new javax.swing.JButton();
        scrollPaneLocalFiles = new javax.swing.JScrollPane();
        tableLocalFiles = new javax.swing.JTable();
        panelRemoteFiles = new javax.swing.JPanel();
        toolBarRemoteFiles = new javax.swing.JToolBar();
        buttonDownload = new javax.swing.JButton();
        buttonNewFolderServer = new javax.swing.JButton();
        buttonRefreshServer = new javax.swing.JButton();
        scrollPaneRemoteFiles = new javax.swing.JScrollPane();
        tableRemoteFiles = new javax.swing.JTable();
        scrollPaneLog = new javax.swing.JScrollPane();
        editorPaneLog = new javax.swing.JEditorPane();
        menuBar = new javax.swing.JMenuBar();
        menuFile = new javax.swing.JMenu();
        menuItemNewConnection = new javax.swing.JMenuItem();
        separatorFile = new javax.swing.JPopupMenu.Separator();
        menuItemConnect = new javax.swing.JMenuItem();
        menuItemDisconnect = new javax.swing.JMenuItem();
        separatorFile2 = new javax.swing.JPopupMenu.Separator();
        menuItemExit = new javax.swing.JMenuItem();
        menuLocal = new javax.swing.JMenu();
        menuItemUpload = new javax.swing.JMenuItem();
        separatorLocal = new javax.swing.JPopupMenu.Separator();
        menuItemNewFolderLocal = new javax.swing.JMenuItem();
        menuItemOpenFile = new javax.swing.JMenuItem();
        menuItemDeleteLocal = new javax.swing.JMenuItem();
        separatorLocal2 = new javax.swing.JPopupMenu.Separator();
        menuItemPropertiesLocal = new javax.swing.JMenuItem();
        menuServer = new javax.swing.JMenu();
        menuItemDownload = new javax.swing.JMenuItem();
        separatorServer = new javax.swing.JPopupMenu.Separator();
        menuItemNewFolderServer = new javax.swing.JMenuItem();
        menuItemDeleteServer = new javax.swing.JMenuItem();
        separatorServer2 = new javax.swing.JPopupMenu.Separator();
        menuItemPropertiesServer = new javax.swing.JMenuItem();
        menuTools = new javax.swing.JMenu();
        menuModoOperacao = new javax.swing.JMenu();
        radioButtonMenuItemOnline = new javax.swing.JRadioButtonMenuItem();
        radioButtonMenuItemOffline = new javax.swing.JRadioButtonMenuItem();
        separatorTools = new javax.swing.JPopupMenu.Separator();
        menuItemTicket = new javax.swing.JMenuItem();
        menuHelp = new javax.swing.JMenu();
        menuItemAbout = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("FTPobre");

        panelToolBox.setPreferredSize(new java.awt.Dimension(600, 30));
        panelToolBox.setLayout(new java.awt.GridLayout(1, 0));

        toolBarFastAccess.setRollover(true);

        buttonConnect.setText("Conectar");
        buttonConnect.setFocusable(false);
        buttonConnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonConnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonConnectActionPerformed(evt);
            }
        });
        toolBarFastAccess.add(buttonConnect);

        buttonDisconnect.setText("Desconectar");
        buttonDisconnect.setEnabled(false);
        buttonDisconnect.setFocusable(false);
        buttonDisconnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonDisconnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonDisconnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonDisconnectActionPerformed(evt);
            }
        });
        toolBarFastAccess.add(buttonDisconnect);
        toolBarFastAccess.add(separatorFastAccess);

        labelOperationMode.setText("Trabalhando Off-Line");
        toolBarFastAccess.add(labelOperationMode);

        panelToolBox.add(toolBarFastAccess);

        getContentPane().add(panelToolBox, java.awt.BorderLayout.NORTH);

        splitPaneContainer.setDividerLocation(400);
        splitPaneContainer.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        splitPaneFileManager.setDividerLocation(400);

        panelLocalFiles.setLayout(new java.awt.BorderLayout());

        toolBarLocalFiles.setFloatable(false);
        toolBarLocalFiles.setRollover(true);

        buttonEnviar.setText("Enviar");
        buttonEnviar.setEnabled(false);
        buttonEnviar.setFocusable(false);
        buttonEnviar.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonEnviar.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonEnviar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonEnviarActionPerformed(evt);
            }
        });
        toolBarLocalFiles.add(buttonEnviar);

        buttonNewFolderLocal.setText("Nova pasta");
        buttonNewFolderLocal.setEnabled(false);
        buttonNewFolderLocal.setFocusable(false);
        buttonNewFolderLocal.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonNewFolderLocal.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonNewFolderLocal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonNewFolderLocalActionPerformed(evt);
            }
        });
        toolBarLocalFiles.add(buttonNewFolderLocal);

        buttonRefreshLocal.setText("Atualizar");
        buttonRefreshLocal.setEnabled(false);
        buttonRefreshLocal.setFocusable(false);
        buttonRefreshLocal.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonRefreshLocal.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonRefreshLocal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonRefreshLocalActionPerformed(evt);
            }
        });
        toolBarLocalFiles.add(buttonRefreshLocal);

        panelLocalFiles.add(toolBarLocalFiles, java.awt.BorderLayout.NORTH);

        tableLocalFiles.setAutoCreateRowSorter(true);
        tableLocalFiles.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        tableLocalFiles.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
        tableLocalFiles.setShowHorizontalLines(false);
        tableLocalFiles.setShowVerticalLines(false);
        tableLocalFiles.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                tableLocalFilesPropertyChange(evt);
            }
        });
        scrollPaneLocalFiles.setViewportView(tableLocalFiles);

        panelLocalFiles.add(scrollPaneLocalFiles, java.awt.BorderLayout.CENTER);

        splitPaneFileManager.setLeftComponent(panelLocalFiles);

        panelRemoteFiles.setLayout(new java.awt.BorderLayout());

        toolBarRemoteFiles.setFloatable(false);
        toolBarRemoteFiles.setRollover(true);

        buttonDownload.setText("Baixar");
        buttonDownload.setEnabled(false);
        buttonDownload.setFocusable(false);
        buttonDownload.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonDownload.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonDownload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonDownloadActionPerformed(evt);
            }
        });
        toolBarRemoteFiles.add(buttonDownload);

        buttonNewFolderServer.setText("Nova pasta");
        buttonNewFolderServer.setEnabled(false);
        buttonNewFolderServer.setFocusable(false);
        buttonNewFolderServer.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonNewFolderServer.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonNewFolderServer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonNewFolderServerActionPerformed(evt);
            }
        });
        toolBarRemoteFiles.add(buttonNewFolderServer);

        buttonRefreshServer.setText("Atualizar");
        buttonRefreshServer.setEnabled(false);
        buttonRefreshServer.setFocusable(false);
        buttonRefreshServer.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonRefreshServer.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonRefreshServer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonRefreshServerActionPerformed(evt);
            }
        });
        toolBarRemoteFiles.add(buttonRefreshServer);

        panelRemoteFiles.add(toolBarRemoteFiles, java.awt.BorderLayout.NORTH);

        tableRemoteFiles.setAutoCreateRowSorter(true);
        tableRemoteFiles.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        tableRemoteFiles.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
        tableRemoteFiles.setShowHorizontalLines(false);
        tableRemoteFiles.setShowVerticalLines(false);
        tableRemoteFiles.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                tableRemoteFilesPropertyChange(evt);
            }
        });
        scrollPaneRemoteFiles.setViewportView(tableRemoteFiles);

        panelRemoteFiles.add(scrollPaneRemoteFiles, java.awt.BorderLayout.CENTER);

        splitPaneFileManager.setRightComponent(panelRemoteFiles);

        splitPaneContainer.setLeftComponent(splitPaneFileManager);

        scrollPaneLog.setViewportView(editorPaneLog);

        splitPaneContainer.setRightComponent(scrollPaneLog);

        getContentPane().add(splitPaneContainer, java.awt.BorderLayout.CENTER);

        menuFile.setText("Arquivo");
        menuFile.addMenuListener(new javax.swing.event.MenuListener() {
            public void menuCanceled(javax.swing.event.MenuEvent evt) {
            }
            public void menuDeselected(javax.swing.event.MenuEvent evt) {
            }
            public void menuSelected(javax.swing.event.MenuEvent evt) {
                menuFileMenuSelected(evt);
            }
        });

        menuItemNewConnection.setText("Nova conexão...");
        menuItemNewConnection.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemNewConnectionActionPerformed(evt);
            }
        });
        menuFile.add(menuItemNewConnection);
        menuFile.add(separatorFile);

        menuItemConnect.setText("Conectar");
        menuItemConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemConnectActionPerformed(evt);
            }
        });
        menuFile.add(menuItemConnect);

        menuItemDisconnect.setText("Desconectar");
        menuItemDisconnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemDisconnectActionPerformed(evt);
            }
        });
        menuFile.add(menuItemDisconnect);
        menuFile.add(separatorFile2);

        menuItemExit.setText("Sair");
        menuItemExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemExitActionPerformed(evt);
            }
        });
        menuFile.add(menuItemExit);

        menuBar.add(menuFile);

        menuLocal.setText("Local");
        menuLocal.addMenuListener(new javax.swing.event.MenuListener() {
            public void menuCanceled(javax.swing.event.MenuEvent evt) {
            }
            public void menuDeselected(javax.swing.event.MenuEvent evt) {
            }
            public void menuSelected(javax.swing.event.MenuEvent evt) {
                menuLocalMenuSelected(evt);
            }
        });

        menuItemUpload.setText("Upload");
        menuItemUpload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemUploadActionPerformed(evt);
            }
        });
        menuLocal.add(menuItemUpload);
        menuLocal.add(separatorLocal);

        menuItemNewFolderLocal.setText("Nova pasta");
        menuItemNewFolderLocal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemNewFolderLocalActionPerformed(evt);
            }
        });
        menuLocal.add(menuItemNewFolderLocal);

        menuItemOpenFile.setText("Abrir");
        menuItemOpenFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemOpenFileActionPerformed(evt);
            }
        });
        menuLocal.add(menuItemOpenFile);

        menuItemDeleteLocal.setText("Excluir");
        menuItemDeleteLocal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemDeleteLocalActionPerformed(evt);
            }
        });
        menuLocal.add(menuItemDeleteLocal);
        menuLocal.add(separatorLocal2);

        menuItemPropertiesLocal.setText("Propriedades");
        menuItemPropertiesLocal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemPropertiesLocalActionPerformed(evt);
            }
        });
        menuLocal.add(menuItemPropertiesLocal);

        menuBar.add(menuLocal);

        menuServer.setText("Servidor");
        menuServer.addMenuListener(new javax.swing.event.MenuListener() {
            public void menuCanceled(javax.swing.event.MenuEvent evt) {
            }
            public void menuDeselected(javax.swing.event.MenuEvent evt) {
            }
            public void menuSelected(javax.swing.event.MenuEvent evt) {
                menuServerMenuSelected(evt);
            }
        });

        menuItemDownload.setText("Download");
        menuItemDownload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemDownloadActionPerformed(evt);
            }
        });
        menuServer.add(menuItemDownload);
        menuServer.add(separatorServer);

        menuItemNewFolderServer.setText("Nova pasta");
        menuItemNewFolderServer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemNewFolderServerActionPerformed(evt);
            }
        });
        menuServer.add(menuItemNewFolderServer);

        menuItemDeleteServer.setText("Excluir");
        menuItemDeleteServer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemDeleteServerActionPerformed(evt);
            }
        });
        menuServer.add(menuItemDeleteServer);
        menuServer.add(separatorServer2);

        menuItemPropertiesServer.setText("Propriedades");
        menuItemPropertiesServer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemPropertiesServerActionPerformed(evt);
            }
        });
        menuServer.add(menuItemPropertiesServer);

        menuBar.add(menuServer);

        menuTools.setText("Ferramentas");

        menuModoOperacao.setText("Modo operação");

        radioButtonMenuItemOnline.setText("On-line");
        radioButtonMenuItemOnline.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioButtonMenuItemOnlineActionPerformed(evt);
            }
        });
        menuModoOperacao.add(radioButtonMenuItemOnline);

        radioButtonMenuItemOffline.setSelected(true);
        radioButtonMenuItemOffline.setText("Off-line");
        radioButtonMenuItemOffline.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioButtonMenuItemOfflineActionPerformed(evt);
            }
        });
        menuModoOperacao.add(radioButtonMenuItemOffline);

        menuTools.add(menuModoOperacao);
        menuTools.add(separatorTools);

        menuItemTicket.setText("Ticket Spekx...");
        menuItemTicket.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemTicketActionPerformed(evt);
            }
        });
        menuTools.add(menuItemTicket);

        menuBar.add(menuTools);

        menuHelp.setText("Ajuda");

        menuItemAbout.setText("Sobre");
        menuItemAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemAboutActionPerformed(evt);
            }
        });
        menuHelp.add(menuItemAbout);

        menuBar.add(menuHelp);

        setJMenuBar(menuBar);

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-800)/2, (screenSize.height-600)/2, 800, 600);
    }// </editor-fold>//GEN-END:initComponents

    private void menuItemExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemExitActionPerformed
    	getInstance().dispatchEvent(new WindowEvent(getInstance(), WindowEvent.WINDOW_CLOSING));
    }//GEN-LAST:event_menuItemExitActionPerformed

    private void menuItemAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemAboutActionPerformed
        AboutFrame aboutFrame = new AboutFrame(this, true);
        aboutFrame.setVisible(true);
    }//GEN-LAST:event_menuItemAboutActionPerformed

    private void menuItemConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemConnectActionPerformed
    	ServerFacade.connect();
    }//GEN-LAST:event_menuItemConnectActionPerformed

    private void menuFileMenuSelected(javax.swing.event.MenuEvent evt) {//GEN-FIRST:event_menuFileMenuSelected
    	ConnectionData c = Main.getConnectionData();
    	this.menuItemConnect.setEnabled(!c.isConnected());
    	this.menuItemDisconnect.setEnabled(c.isConnected());
    }//GEN-LAST:event_menuFileMenuSelected

    private void menuItemUploadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemUploadActionPerformed
    	ServerFacade.upload();
    }//GEN-LAST:event_menuItemUploadActionPerformed

    private void menuItemDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemDownloadActionPerformed
    	ServerFacade.download();
    }//GEN-LAST:event_menuItemDownloadActionPerformed

    private void menuItemDeleteServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemDeleteServerActionPerformed
    	DeleteFileFacade.deleteFile(DeleteRemoteFileCommand.class);
    }//GEN-LAST:event_menuItemDeleteServerActionPerformed

    private void tableLocalFilesPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_tableLocalFilesPropertyChange
        if (evt.getPropertyName().equals("model")) {
            this.configureLocalFilesTable();
        }
    }//GEN-LAST:event_tableLocalFilesPropertyChange

    private void tableRemoteFilesPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_tableRemoteFilesPropertyChange
        if (evt.getPropertyName().equals("model")) {
            this.configureRemoteFilesTable();
            this.saveLocalRemoteFilesTableData();
        }
    }//GEN-LAST:event_tableRemoteFilesPropertyChange

    private void menuItemOpenFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemOpenFileActionPerformed
        FileFacade.openFile();
    }//GEN-LAST:event_menuItemOpenFileActionPerformed

    private void menuServerMenuSelected(javax.swing.event.MenuEvent evt) {//GEN-FIRST:event_menuServerMenuSelected
    	ConnectionData c = Main.getConnectionData();
        
        boolean anyFileSelected = false;
        RemoteFile file = RemoteFileUtil.getSelectedFile();
        if (file != null) {
        	anyFileSelected = !file.isDirectory();
        }
         
        this.menuItemDownload.setEnabled(c.isConnected() && anyFileSelected);
        this.menuItemNewFolderServer.setEnabled(c.isConnected());
        
        boolean validFileOrFolder = (file != null) && (!RemoteFile.getUpFolder().equals(file));
        this.menuItemDeleteServer.setEnabled(c.isConnected() && validFileOrFolder);
        this.menuItemPropertiesServer.setEnabled(c.isConnected() && validFileOrFolder);
        
    }//GEN-LAST:event_menuServerMenuSelected

    private void menuItemPropertiesLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemPropertiesLocalActionPerformed
        FileFacade.showProperties(true);
    }//GEN-LAST:event_menuItemPropertiesLocalActionPerformed

    private void menuLocalMenuSelected(javax.swing.event.MenuEvent evt) {//GEN-FIRST:event_menuLocalMenuSelected
        boolean anyFileSelected = false;
        LocalFile file = LocalFileUtil.getSelectedFile();
        if (file != null) {
        	anyFileSelected = !file.isDirectory();
        }
        
        this.menuItemNewFolderLocal.setEnabled(!this.localFilePath.isEmpty());
        this.menuItemUpload.setEnabled(anyFileSelected);
        this.menuItemOpenFile.setEnabled(anyFileSelected);
        
        boolean validFileOrFolder = (file != null) && (!LocalFile.getUpFolder().equals(file));
        this.menuItemDeleteLocal.setEnabled(validFileOrFolder);
        this.menuItemPropertiesLocal.setEnabled(validFileOrFolder);
    }//GEN-LAST:event_menuLocalMenuSelected

    private void menuItemNewFolderLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemNewFolderLocalActionPerformed
    	FileFacade.createFolder(true);
    }//GEN-LAST:event_menuItemNewFolderLocalActionPerformed

    private void menuItemDeleteLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemDeleteLocalActionPerformed
    	DeleteFileFacade.deleteFile(DeleteLocalFileCommand.class);
    }//GEN-LAST:event_menuItemDeleteLocalActionPerformed

    private void menuItemNewFolderServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemNewFolderServerActionPerformed
    	FileFacade.createFolder(false);
    }//GEN-LAST:event_menuItemNewFolderServerActionPerformed

    private void menuItemPropertiesServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemPropertiesServerActionPerformed
        FileFacade.showProperties(false);
    }//GEN-LAST:event_menuItemPropertiesServerActionPerformed

    private void buttonEnviarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEnviarActionPerformed
    	ServerFacade.upload();
    }//GEN-LAST:event_buttonEnviarActionPerformed

    private void buttonNewFolderLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonNewFolderLocalActionPerformed
    	FileFacade.createFolder(true);
    }//GEN-LAST:event_buttonNewFolderLocalActionPerformed

    private void buttonRefreshLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRefreshLocalActionPerformed
    	try {
        	CommandFactory.command(RefreshLocalFilesViewCommand.class).execute();
        } catch (Exception ex) {
        	MensagensUtil.showErrorMessage("Erro", "Ocorreu um erro na atualização das informações dos arquivos locais. Detalhe: " + ex.getMessage());
        	logger.log(Level.SEVERE, ex.getMessage(), ex);
        }
    }//GEN-LAST:event_buttonRefreshLocalActionPerformed

    private void buttonDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDownloadActionPerformed
    	ServerFacade.download();
    }//GEN-LAST:event_buttonDownloadActionPerformed

    private void buttonNewFolderServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonNewFolderServerActionPerformed
        FileFacade.createFolder(false);
    }//GEN-LAST:event_buttonNewFolderServerActionPerformed

    private void buttonRefreshServerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRefreshServerActionPerformed
    	try {
        	CommandFactory.command(RefreshRemoteFilesViewCommand.class).execute();
        } catch (Exception ex) {
        	MensagensUtil.showErrorMessage("Erro", "Ocorreu um erro na atualização das informações dos arquivos do Servidor FTP. Detalhe: " + ex.getMessage());
        	logger.log(Level.SEVERE, ex.getMessage(), ex);
        }
    }//GEN-LAST:event_buttonRefreshServerActionPerformed

    private void menuItemDisconnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemDisconnectActionPerformed
    	ServerFacade.disconnect();
    }//GEN-LAST:event_menuItemDisconnectActionPerformed

    private void buttonConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonConnectActionPerformed
    	ServerFacade.connect();
    }//GEN-LAST:event_buttonConnectActionPerformed

    private void buttonDisconnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDisconnectActionPerformed
        ServerFacade.disconnect();
    }//GEN-LAST:event_buttonDisconnectActionPerformed

    private void radioButtonMenuItemOnlineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioButtonMenuItemOnlineActionPerformed
        ServerFacade.connect();
    }//GEN-LAST:event_radioButtonMenuItemOnlineActionPerformed

    private void radioButtonMenuItemOfflineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioButtonMenuItemOfflineActionPerformed
        ServerFacade.disconnect();
    }//GEN-LAST:event_radioButtonMenuItemOfflineActionPerformed

    private void menuItemNewConnectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemNewConnectionActionPerformed
        ConnectionFrame frame = new ConnectionFrame(this, true, true);
        frame.setVisible(true);
    }//GEN-LAST:event_menuItemNewConnectionActionPerformed

    private void menuItemTicketActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemTicketActionPerformed
        CreateSpekxTicketModelFrame frame = new CreateSpekxTicketModelFrame(this, true);
        frame.setVisible(true);
    }//GEN-LAST:event_menuItemTicketActionPerformed

    public void configureComponentState(boolean enabled) {
        this.buttonDisconnect.setEnabled(enabled);
        this.buttonConnect.setEnabled(!enabled);
        this.buttonRefreshServer.setEnabled(enabled);
        this.radioButtonMenuItemOnline.setSelected(enabled);
        this.radioButtonMenuItemOffline.setSelected(!enabled);
    }

    public void activeComponentState() {
        this.buttonNewFolderLocal.setEnabled(true);
        this.buttonNewFolderServer.setEnabled(true);
        this.buttonEnviar.setEnabled(true);
        this.buttonDownload.setEnabled(true);
        this.buttonRefreshLocal.setEnabled(true);
    }

    public void configureLabelOperationMode(boolean online) {
        online = (online && Main.getConnectionData().isConnected());
        this.labelOperationMode.setText("Trabalhando " + ((online) ? "On-line" : "Off-line"));
        this.labelOperationMode.setForeground((online) ? Color.GREEN : Color.RED);
        this.labelOperationMode.setFont(new Font("Tahoma", Font.BOLD, 11));
    }
    
    private void configureLocalFilesTable() {
    	TableColumnModel model = this.tableLocalFiles.getTableHeader().getColumnModel();
        model.getColumn(0).setPreferredWidth(45);
        model.getColumn(1).setPreferredWidth(330);
        model.getColumn(2).setPreferredWidth(90);
    }
    
    private void configureRemoteFilesTable() {
    	TableColumnModel model = this.tableRemoteFiles.getTableHeader().getColumnModel();
        model.getColumn(0).setPreferredWidth(45);
        model.getColumn(1).setPreferredWidth(330);
        model.getColumn(2).setPreferredWidth(90);
    }
    
    private void saveLocalRemoteFilesTableData() {
    	String name = FileNameGenerator.generateFileName(this.getAbsolutePathFromRemoteFilePath()) + ".xml";
        File file = new File(LocalFileUtil.getCacheFolder().getAbsolutePath() + "/" + name);
        
        try {
			XmlFacade.writeTableModelToXml(this.tableRemoteFiles.getModel(), file);
		} catch (Exception ex) {
			FtpLogView.log("Ocorreu um erro ao salvar estado do modelo de arquivos remotos. Detalhe: " + ex.getMessage());
			logger.log(Level.SEVERE, ex.getMessage(), ex);
			ex.printStackTrace();
		}
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonConnect;
    private javax.swing.JButton buttonDisconnect;
    private javax.swing.JButton buttonDownload;
    private javax.swing.JButton buttonEnviar;
    private javax.swing.JButton buttonNewFolderLocal;
    private javax.swing.JButton buttonNewFolderServer;
    private javax.swing.JButton buttonRefreshLocal;
    private javax.swing.JButton buttonRefreshServer;
    private javax.swing.JEditorPane editorPaneLog;
    private javax.swing.JLabel labelOperationMode;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenu menuFile;
    private javax.swing.JMenu menuHelp;
    private javax.swing.JMenuItem menuItemAbout;
    private javax.swing.JMenuItem menuItemConnect;
    private javax.swing.JMenuItem menuItemDeleteLocal;
    private javax.swing.JMenuItem menuItemDeleteServer;
    private javax.swing.JMenuItem menuItemDisconnect;
    private javax.swing.JMenuItem menuItemDownload;
    private javax.swing.JMenuItem menuItemExit;
    private javax.swing.JMenuItem menuItemNewConnection;
    private javax.swing.JMenuItem menuItemNewFolderLocal;
    private javax.swing.JMenuItem menuItemNewFolderServer;
    private javax.swing.JMenuItem menuItemOpenFile;
    private javax.swing.JMenuItem menuItemPropertiesLocal;
    private javax.swing.JMenuItem menuItemPropertiesServer;
    private javax.swing.JMenuItem menuItemTicket;
    private javax.swing.JMenuItem menuItemUpload;
    private javax.swing.JMenu menuLocal;
    private javax.swing.JMenu menuModoOperacao;
    private javax.swing.JMenu menuServer;
    private javax.swing.JMenu menuTools;
    private javax.swing.JPanel panelLocalFiles;
    private javax.swing.JPanel panelRemoteFiles;
    private javax.swing.JPanel panelToolBox;
    private javax.swing.JRadioButtonMenuItem radioButtonMenuItemOffline;
    private javax.swing.JRadioButtonMenuItem radioButtonMenuItemOnline;
    private javax.swing.JScrollPane scrollPaneLocalFiles;
    private javax.swing.JScrollPane scrollPaneLog;
    private javax.swing.JScrollPane scrollPaneRemoteFiles;
    private javax.swing.JToolBar.Separator separatorFastAccess;
    private javax.swing.JPopupMenu.Separator separatorFile;
    private javax.swing.JPopupMenu.Separator separatorFile2;
    private javax.swing.JPopupMenu.Separator separatorLocal;
    private javax.swing.JPopupMenu.Separator separatorLocal2;
    private javax.swing.JPopupMenu.Separator separatorServer;
    private javax.swing.JPopupMenu.Separator separatorServer2;
    private javax.swing.JPopupMenu.Separator separatorTools;
    private javax.swing.JSplitPane splitPaneContainer;
    private javax.swing.JSplitPane splitPaneFileManager;
    private javax.swing.JTable tableLocalFiles;
    private javax.swing.JTable tableRemoteFiles;
    private javax.swing.JToolBar toolBarFastAccess;
    private javax.swing.JToolBar toolBarLocalFiles;
    private javax.swing.JToolBar toolBarRemoteFiles;
    // End of variables declaration//GEN-END:variables
    private Stack<String> localFilePath;
    private Stack<String> remoteFilePath;
    
    private class WindowAction implements WindowListener {

		@Override
		public void windowActivated(WindowEvent arg0) {		}

		@Override
		public void windowClosed(WindowEvent arg0) {		}

		@Override
		public void windowClosing(WindowEvent evt) {
			ICommand command = CommandFactory.command(DisconnectionCommand.class);
			if (!command.canExecute()) {
				getInstance().dispose();
				return;
			}
			
			try {
				command.execute();
				getInstance().dispose();
			} catch (Exception ex) {
				int option = MensagensUtil.showConfirmationMessage("Erro ao desconectar", 
						"Não foi possível encerrar conexão com o servidor FTP. Detalhe: " +
						ex.getMessage() + "\nDeseja encerrar a aplicação?", MensagensUtil.WARNING);
				
				if (option == 0) {
					getInstance().dispose();
				}
			}
		}

		@Override
		public void windowDeactivated(WindowEvent arg0) {		}

		@Override
		public void windowDeiconified(WindowEvent arg0) {		}

		@Override
		public void windowIconified(WindowEvent arg0) {		}

		@Override
		public void windowOpened(WindowEvent evt) {
                    configureLabelOperationMode(false);
                    ConnectionFrame frame = new ConnectionFrame(getInstance(), true, false);
                    frame.setVisible(true);
		}    	
    }
    
    private class TableLocalFileOpenPathAction implements MouseListener, KeyListener {

		@Override
		public void mouseClicked(MouseEvent evt) {
			if (evt.getClickCount() == 2) {
				this.openFolder();
			}
		}
		
		private void openFolder() {
			LocalFile file = LocalFileUtil.getSelectedFile();
			
			if (file.equals(LocalFile.getUpFolder())) {
				if (localFilePath.size() > 1) {
					localFilePath.pop();
				}
			} else if (file.isDirectory()) {
				localFilePath.push(file.getName());
			} else {
				FileFacade.openFile();
			}
			
			tableLocalFiles.setModel(
					FileTableModelBuilder.createLocalFilesTableModel(getAbsolutePathFromLocalFilePath()));
		}

		@Override
		public void mouseEntered(MouseEvent e) {		}

		@Override
		public void mouseExited(MouseEvent e) {		}

		@Override
		public void mousePressed(MouseEvent e) {		}

		@Override
		public void mouseReleased(MouseEvent e) {		}

        @Override
        public void keyTyped(KeyEvent e) {        }

        @Override
        public void keyPressed(KeyEvent e) {
            if (KeyEvent.VK_ENTER == e.getKeyCode()) {
                this.openFolder();
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {        }
    }
	
	private class TableLocalFilePopup implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {			}

		@Override
		public void mouseEntered(MouseEvent e) {			}

		@Override
		public void mouseExited(MouseEvent e) {			}

		@Override
		public void mousePressed(MouseEvent evt) {
			if (evt.getButton() != MouseEvent.BUTTON3) {
				return;
			}
			
			this.selectRow(evt);
			this.showPopup(evt);
		}

		@Override
		public void mouseReleased(MouseEvent e) {			}
		
		private void selectRow(MouseEvent evt) {
			int row = tableLocalFiles.rowAtPoint(evt.getPoint());
			tableLocalFiles.setRowSelectionInterval(row, row);
		}
		
		private void showPopup(MouseEvent evt) {
			Boolean objectIsFolder = this.isFolder();
			if (objectIsFolder == null) {
				return;
			} else if (objectIsFolder) {
				LocalFolderPopup popup = new LocalFolderPopup();
				popup.show(evt.getComponent(), evt.getX(), evt.getY());
			} else {
				LocalFilePopup popup = new LocalFilePopup();
				popup.show(evt.getComponent(), evt.getX(), evt.getY());
			}
		}
		
		private Boolean isFolder() {
			LocalFile file = LocalFileUtil.getSelectedFile();
			
			if (LocalFile.getUpFolder().equals(file)) {
				return null;
			}
			
			return file.isDirectory();
		}
	}
    
    private class TableRemoteFileOpenPathAction implements MouseListener, KeyListener {

		@Override
		public void mouseClicked(MouseEvent evt) {
			if (evt.getClickCount() == 2) {
				this.openFolder();
			}
		}
		
		private void openFolder() {
			RemoteFile file = RemoteFileUtil.getSelectedFile();
			
			if (!file.getFile().isDirectory()) {
				return;
			}
			
			if (file.equals(RemoteFile.getUpFolder())) {
				if (remoteFilePath.size() > 0) {
					remoteFilePath.pop();
				}
			} else {
				remoteFilePath.push(file.getFile().getName());
			}				
			
			tableRemoteFiles.setModel(
					FileTableModelBuilder.createRemoteFilesTableModel(getAbsolutePathFromRemoteFilePath()));
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {		}

		@Override
		public void mouseExited(MouseEvent arg0) {		}

		@Override
		public void mousePressed(MouseEvent arg0) {		}

		@Override
		public void mouseReleased(MouseEvent arg0) {		}

        @Override
        public void keyTyped(KeyEvent e) {        }

        @Override
        public void keyPressed(KeyEvent e) {
            if (KeyEvent.VK_ENTER == e.getKeyCode()) {
                this.openFolder();
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {        }
    }
	
	private class TableRemoteFilePopup implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {			}

		@Override
		public void mouseEntered(MouseEvent e) {			}

		@Override
		public void mouseExited(MouseEvent e) {			}

		@Override
		public void mousePressed(MouseEvent evt) {
			if (evt.getButton() != MouseEvent.BUTTON3) {
				return;
			}
			
			this.selectRow(evt);
			this.showPopup(evt);
		}

		@Override
		public void mouseReleased(MouseEvent e) {			}
		
		private void selectRow(MouseEvent evt) {
			int row = tableRemoteFiles.rowAtPoint(evt.getPoint());
			tableRemoteFiles.setRowSelectionInterval(row, row);
		}
		
		private void showPopup(MouseEvent evt) {
			Boolean objectIsFolder = this.isFolder();
			if (objectIsFolder == null) {
				return;
			} else if (objectIsFolder) {
				RemoteFolderPopup popup = new RemoteFolderPopup();
				popup.show(evt.getComponent(), evt.getX(), evt.getY());
			} else {
				RemoteFilePopup popup = new RemoteFilePopup();
				popup.show(evt.getComponent(), evt.getX(), evt.getY());
			}
		}
		
		private Boolean isFolder() {
			RemoteFile file = RemoteFileUtil.getSelectedFile();
			
			if (RemoteFile.getUpFolder().equals(file)) {
				return null;
			}
			
			return file.isDirectory();
		}
	}
}